package io.youngledo.usb.license;

import lombok.extern.slf4j.Slf4j;

import java.net.NetworkInterface;
import java.security.MessageDigest;
import java.util.Enumeration;
import java.util.HexFormat;

/// 机器ID生成器
///
/// 生成基于硬件特征的唯一机器标识符，用于许可证设备绑定。
///
/// ## 生成方式
/// 使用以下硬件特征组合生成唯一ID：
/// - MAC地址（网络接口物理地址）
/// - 操作系统名称和版本
/// - 用户主目录路径
///
/// 通过SHA-256哈希生成固定长度的机器ID。
///
/// ## 注意事项
/// - 机器ID绑定可以防止许可证在不同设备间共享
/// - 但也会给用户带来不便（换机器需要重新激活）
/// - 建议根据实际需求决定是否启用此功能
@Slf4j
public class MachineIdGenerator {

    /// 获取当前机器的唯一标识符
    ///
    /// @return 机器ID（SHA-256哈希值，64位十六进制字符串）
    public static String getMachineId() {
        try {
            var sb = new StringBuilder();

            // 1. 获取MAC地址
            var macAddress = getMacAddress();
            if (macAddress != null) {
                sb.append(macAddress);
            }

            // 2. 操作系统信息
            sb.append(System.getProperty("os.name"));
            sb.append(System.getProperty("os.version"));

            // 3. 用户主目录（增加唯一性）
            sb.append(System.getProperty("user.home"));

            // 生成SHA-256哈希
            var digest = MessageDigest.getInstance("SHA-256");
            var hash = digest.digest(sb.toString().getBytes());
            var machineId = HexFormat.of().formatHex(hash);

            log.debug("机器ID生成成功: {}", machineId);
            return machineId;

        } catch (Exception e) {
            log.error("生成机器ID失败", e);
            return "UNKNOWN-MACHINE-ID";
        }
    }

    /// 获取第一个可用的MAC地址
    ///
    /// @return MAC地址字符串，如果获取失败返回null
    private static String getMacAddress() {
        try {
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (networkInterfaces.hasMoreElements()) {
                var networkInterface = networkInterfaces.nextElement();
                var mac = networkInterface.getHardwareAddress();

                // 跳过虚拟网卡和回环接口
                if (mac != null && mac.length > 0 && !networkInterface.isLoopback() && !networkInterface.isVirtual()) {
                    var sb = new StringBuilder();
                    for (int i = 0; i < mac.length; i++) {
                        sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
                    }
                    return sb.toString();
                }
            }
        } catch (Exception e) {
            log.warn("获取MAC地址失败", e);
        }
        return null;
    }

    /// 主方法：用于测试和查看当前机器ID
    ///
    /// **使用方法**:
    /// ```bash
    /// java io.youngledo.usb.license.MachineIdGenerator
    /// ```
    public static void main(String[] args) {
        System.out.println("========================================");
        System.out.println("🖥️  当前机器ID");
        System.out.println("========================================");
        System.out.println("机器ID: " + getMachineId());
        System.out.println("========================================");
        System.out.println("\n💡 提示：");
        System.out.println("- 此ID用于许可证设备绑定");
        System.out.println("- 重装系统或更换硬件可能导致ID变化");
        System.out.println("- 建议在生成许可证时记录此ID");
        System.out.println("========================================\n");
    }
}
